﻿//【进阶】43.智能指针(1)
//【进阶】44.智能指针(2)
//【头文件包含】
//C++的主要头文件
#include<iostream>//c++的输入输出流
using namespace std;
#include<algorithm>
#include<string>
#include<vector>
#include<list>
//C的主要头文件
//#include<stdio.h>
//#include<stdlib.h>
//#include<assert.h>
//#include<string.h> 
#include <thread>
#include <mutex>
#include <atomic>
#include "SmartPtr.h"

//【命名空间】

//【类声明】
struct ListNode
{
	int _data;
	/*myspace::Shared_Ptr<ListNode> _prev;
	myspace::Shared_Ptr<ListNode> _next;*/
	myspace::Weak_Ptr<ListNode> _prev;
	myspace::Weak_Ptr<ListNode> _next;
	~ListNode() { cout << "~ListNode()" << endl; }
};


//【函数声明】
void Test1();void Test2();void Test3();void Test4();

//【主函数】
int main()
{
	cout << "****主函数开始****" << endl;
	try 
	{
		Test1();
		Test2();
	}
	catch (string& e)
	{
		cout << e << endl;
	}
	Test3();
	Test4();
	
	cout << "****主函数结束****" << endl;
	return 0;
}

//【函数定义】
void div(int* p)
{
	if (*p == 0) throw (string)"error";
	else cout << "right num:" << *p << endl;
}
void div2(const SmartPtr<int>& p)
{
	if (*p == 0) throw (string)"error";
	else cout << "right num:" << *p << endl;
}
/*测试用例*/void Test1()
{
	cout << "****测试用例1开始****"<< endl;
	int* p = new int;
	*p=3;
	div(p);//如果这里抛出异常那delete p无法执行
	delete p;
	cout << "Test1 delete success" << endl;
	cout << "****测试用例1结束****" << endl << endl;
}

/*测试用例*/void Test2()
{
	cout << "****测试用例2开始****" << endl;
	//int* p = new int;
	//SmartPtr<int> sp(p);//即使抛异常也会释放p开辟的空间
	SmartPtr<int> sp(new int);
	//cin>> *sp;
	*sp=4;
	div2(sp);//如果这里抛出异常那delete p无法执行
	//delete sp;
	cout << "Test1 delete success" << endl;

	cout << "****测试用例2结束****" << endl<<endl;
}

/*测试用例*/void Test3()
{
	cout << "****测试用例3开始****" << endl;
	myspace::Auto_Ptr<int> ap1(new int);
	myspace::Auto_Ptr<int> ap2(ap1);
	//*ap1 = 10;//会导致空指针访问出错

	myspace::Unique_Ptr<int> up1(new int);
	//myspace::Unique_Ptr<int> up2(up1);

	myspace::Shared_Ptr<int> sp1(new int);
	myspace::Shared_Ptr<int> sp2(sp1);
	myspace::Shared_Ptr<int> sp3(new int);
	sp3 = sp2;
	cout << sp3.use_count() << endl;

	myspace::Shared_Ptr<int> sp4(new int);
	cout << sp4.use_count() << endl;
	int n = 10000;

	std::thread t1([&]() {
		for(int i=0;i<n;++i)
		{
			myspace::Shared_Ptr<int> sp5(sp4);
		}
	
		});

	std::thread t2([&]() {
		for (int i = 0;i < n;++i)
		{
			myspace::Shared_Ptr<int> sp6(sp4);
		}
		});

	t1.join();
	t2.join();
	cout << sp4.use_count() << endl;

	cout << "****测试用例3结束****" << endl << endl;
}

/*测试用例*/void Test4()
{
	cout << "****测试用例4开始****" << endl;
	myspace::Shared_Ptr<ListNode> node1(new ListNode);
	myspace::Shared_Ptr<ListNode> node2(new ListNode);
	cout << node1.use_count()<< endl;
	cout << node2.use_count() << endl;
	node1->_next = node2;
	node2->_prev = node1;
	cout << node1.use_count() << endl;
	cout << node2.use_count() << endl;
	cout << "****测试用例4结束****" << endl << endl;
}




//【笔记】
//【进阶】43.智能指针(1)
	//C++中没有GC（垃圾资源回收），new/malloc等资源需要手动释放 
		// new     malloc  fopen   lock
		// delete  free    fclose  unlock
	// RAII（Resource Acquisition Is Initialization）是一种利用对象生命周期来控制程序资源
	// 智能指针是依靠RAII实现的，它是在创建空间时将空间地址再托管给一个智能指针类
	// 创建的对象会在该对象生命周期结束时会自动析构释放对应空间
//【进阶】44.智能指针(2)
	// 同时智能指针还需要实现像指针一样的功能如*、->
	// 问题：如果智能指针发生拷贝构造，那么多个指针指向同一个空间，那么会出现重复析构问题
	// 解决方法有三
		// 1. 管理权转移 auto_ptr 
			// 拷贝时新指针复制原指针，但原指针置空，相当于资源转移
			// 存在缺陷，实际工程不要使用 
		// 2. 防拷贝     unique_ptr
			// 禁止拷贝构造和赋值符号重载，但就不能满足需要实现拷贝的场景
		// 3. 引用计数的共享拷贝 shared_ptr,其中循环引用还要用weak_ptr解决
			// 利用一个引用计数指针计算赋值或拷贝次数，利用一个锁指针给每次++--操作上锁保护
			// 但在循环引用时会出问题，需要用弱指针以避免不必要的引用计数增加


		









